﻿using System;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
using exception = System.Exception;
using System.Reflection;
using System.Drawing;
using Microsoft.Office.Interop.Word;
using MSWord = Microsoft.Office.Interop.Word;
using System.Drawing.Imaging;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Runtime.Serialization.Json;
using System.Collections.Generic;

namespace Client.modules.output
{
    /// <summary>
    /// output 的摘要说明
    /// </summary>
    public class export : IHttpHandler
    {

        private MSWord.Application wordApp;  //Word应用程序变量
        private MSWord.Document wordDoc;     //Word文档变量
        private Object Nothing = Missing.Value;
        public void ProcessRequest(HttpContext context)
        {
            string type = context.Request["type"];
            try
            {
                /*导出到excel*/
                if (type == "excel")
                {
                    string data = decodeHtml(context.Request["bodyHtml"]);
                    string styleCss = context.Request["styleCss"];
                    string name = context.Request["filename"];

                    ResultModel result = new ResultModel();
                    if (string.IsNullOrEmpty(data) || string.IsNullOrEmpty(name) || string.IsNullOrEmpty(type))
                    {
                        result = new ResultModel("false", "", "");
                        return;
                    }
                    //处理数据
                    string ss = CreateExcelString(data, styleCss);
                    Stream strem = GetStream(ss);
                    string FilePath = HttpContext.Current.Server.MapPath("~/temp/") + name + ".xls";
                    string fileURL = "../temp/" + name + ".xls";
                    FileInfo fi = new FileInfo(FilePath);
                    //判断文件是否已经存在,如果存在就删除! 
                    if (fi.Exists)
                    {
                        fi.Delete();
                    }
                    StreamToFile(strem, FilePath);
                    result = new ResultModel("true", fileURL, FilePath);
                    //返回结果
                    context.Response.ContentType = "text/json";
                    JavaScriptSerializer js = new JavaScriptSerializer();
                    string dd = js.Serialize(result);
                    context.Response.Write(dd);
                }
                /*导出到word*/
                else if (type == "word")
                {
                    string data = decodeHtml(context.Request["bodyHtml"]);
                    string styleCss = context.Request["styleCss"];
                    string name = context.Request["filename"];
                    string imageJson = context.Request["imageJson"];

                    ResultModel result = new ResultModel();
                    if (string.IsNullOrEmpty(data) || string.IsNullOrEmpty(name) || string.IsNullOrEmpty(type))
                    {
                        result = new ResultModel("false", "", "");
                        return;
                    }
                    //处理数据
                    string ss = CreateWordString(data, styleCss);
                    string FilePath = HttpContext.Current.Server.MapPath("~/temp/") + name + ".html";
                    string fileURL = "../temp/" + name + ".html";
                    string FilePath_2 = HttpContext.Current.Server.MapPath("~/temp/");

                    FileInfo fi = new FileInfo(FilePath);
                    //判断文件是否已经存在,如果存在就删除! 
                    if (fi.Exists)
                    {
                        fi.Delete();
                    }
                    using (StreamWriter writer = new StreamWriter(FilePath, false, System.Text.Encoding.GetEncoding("gb2312"), 512))
                    {
                        writer.WriteLine(ss);
                    }
                    //if (!((imageJson == null || imageJson == "")))
                    ConvertHtmlToMht(FilePath, FilePath_2, imageJson);

                    result = new ResultModel("true", fileURL, FilePath);
                    //返回结果
                    context.Response.ContentType = "text/json";
                    JavaScriptSerializer js = new JavaScriptSerializer();
                    string dd = js.Serialize(result);
                    context.Response.Write(dd);
                }
                /*导出到txt*/
                else if (type == "txt")
                {

                }
                else if (type == "base64PNG")
                {
                    string base64PNG = context.Request["base64PNG"];
                    byte[] bytes = Convert.FromBase64String(base64PNG);

                    string name = DateTime.Now.Ticks.ToString();
                    string FilePath = HttpContext.Current.Server.MapPath("~/temp/") + name + ".PNG";
                    string fileURL = "../temp/" + name + ".PNG";

                    // 把 byte[] 写入文件 
                    FileStream fs = new FileStream(FilePath, FileMode.Create);
                    BinaryWriter bw = new BinaryWriter(fs, Encoding.UTF8);
                    bw.Write(bytes);
                    bw.Close();
                    fs.Close();

                    context.Response.ContentType = "text/json";
                    JavaScriptSerializer js = new JavaScriptSerializer();

                    ResultModel result = new ResultModel("true", fileURL, FilePath);
                    string dd = js.Serialize(result);
                    context.Response.Write(dd);
                }

            }
            catch (Exception ex)
            {
                context.Response.Write("导出" + type + "异常:" + ex.Message);
            }
        }
        /// <summary>
        /// 创建excel文件流
        /// </summary>
        /// <param name="tableHtml"></param>
        /// <param name="styleCss"></param>
        /// <returns></returns>
        public string CreateExcelString(string tableHtml, string styleCss)
        {
            StringBuilder strb = new StringBuilder();
            strb.Append(" <html xmlns:o=\"urn:schemas-microsoft-com:office:office\"");
            strb.Append("xmlns:x=\"urn:schemas-microsoft-com:office:excel\"");
            strb.Append("xmlns=\"http://www.w3.org/TR/REC-html40\"");
            strb.Append("<head>");
            strb.Append("<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>");
            strb.Append(" <xml>");
            strb.Append(" <x:ExcelWorkbook>");
            strb.Append("  <x:ExcelWorksheets>");
            strb.Append("  <x:ExcelWorksheet>");
            strb.Append("    <x:Name>Sheet1 </x:Name>");
            strb.Append("    <x:WorksheetOptions>");
            strb.Append("    <x:DefaultRowHeight>285 </x:DefaultRowHeight>");
            strb.Append("    <x:Selected/>");
            strb.Append("    <x:Panes>");
            strb.Append("      <x:Pane>");
            strb.Append("      <x:Number>3 </x:Number>");
            strb.Append("      <x:ActiveCol>1 </x:ActiveCol>");
            strb.Append("      </x:Pane>");
            strb.Append("    </x:Panes>");
            strb.Append("    <x:ProtectContents>False </x:ProtectContents>");
            strb.Append("    <x:ProtectObjects>False </x:ProtectObjects>");
            strb.Append("    <x:ProtectScenarios>False </x:ProtectScenarios>");
            strb.Append("    </x:WorksheetOptions>");
            strb.Append("  </x:ExcelWorksheet>");
            strb.Append("  <x:WindowHeight>6750 </x:WindowHeight>");
            strb.Append("  <x:WindowWidth>10620 </x:WindowWidth>");
            strb.Append("  <x:WindowTopX>480 </x:WindowTopX>");
            strb.Append("  <x:WindowTopY>75 </x:WindowTopY>");
            strb.Append("  <x:ProtectStructure>False </x:ProtectStructure>");
            strb.Append("  <x:ProtectWindows>False </x:ProtectWindows>");
            strb.Append(" </x:ExcelWorkbook>");
            strb.Append(" </xml>");
            strb.Append(" <style type=\"text/css\">");
            strb.Append(".xl26");
            strb.Append(" {mso-style-parent:style0;");
            strb.Append(" font-family:\"Times New Roman\", serif;");
            strb.Append(" mso-font-charset:0;");
            strb.Append(" mso-number-format:\"@\";}");
            strb.Append(styleCss);
            strb.Append(" </style>");
            strb.Append("</head>");
            strb.Append("<body>");
            strb.Append(tableHtml);
            strb.Append("</body>");
            strb.Append("</html>");
            return strb.ToString();
        }

        /// <summary>
        /// 创建word文件流
        /// </summary>
        /// <param name="bodyHtml"></param>
        /// <param name="styleCss"></param>
        /// <returns></returns>
        public string CreateWordString(string bodyHtml, string styleCss)
        {
            StringBuilder strb = new StringBuilder();
            strb.Append("<html xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns: o =\"urn:schemas-microsoft-com:office:office\"  xmlns: w =\"urn:schemas-microsoft-com:office:word\"  xmlns: m =\"http://schemas.microsoft.com/office/2004/12/omml\" xmlns =\"http://www.w3.org/TR/REC-html40\"> ");
            strb.Append("<head>");
            strb.Append(" <meta http-equiv=Content-Type content=\"text/html; charset=gb2312\">");
            strb.Append("<meta name=ProgId content=Word.Document>");
            strb.Append("<meta name=Generator content=\"Microsoft Word 15\">");
            strb.Append("<meta name=Originator content=\"Microsoft Word 15\">");
            strb.Append("<style type=\"text/css\">");
            strb.Append(styleCss);
            strb.Append("</style>");
            strb.Append("</head>");
            strb.Append("<body>");
            strb.Append(bodyHtml);
            strb.Append("</body>");
            strb.Append("</html>");
            return strb.ToString();
        }

        public void ConvertHtmlToMht(string html, string url, string imageJson)
        {
            string mht = url + Guid.NewGuid().ToString() + ".mht";

            ConvertHtmlUrlToMht(html, mht);
            Document workDoc = SaveAsWord(mht);

            List<imageModel> imageJsonDe;
            DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(List<imageModel>));
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(imageJson)))
            {
                imageJsonDe = json.ReadObject(ms) as List<imageModel>;
            }

            foreach (Bookmark mark in wordDoc.Bookmarks)
            {
                //定义该插入的图片是否为外部链接       
                Object linkToFile = false;      //默认         
                //定义要插入的图片是否随Word文档一起保存       
                Object saveWithDocument = true;               //默认        
                //使用InlineShapes.AddPicture方法插入图片 
                object range = mark.Range;

                string name = mark.Name;

                foreach (imageModel jsm in imageJsonDe)
                {
                    if (name == jsm.name)
                    {

                        string base64 = jsm.base64;
                        string imgFile = url + Guid.NewGuid().ToString() + ".png";
                        ToImage(base64, imgFile, jsm.width, jsm.height);
                        wordDoc.InlineShapes.AddPicture(imgFile, ref linkToFile, ref saveWithDocument, ref range);
                        break;
                    }
                }
            }

            FileInfo fi = new FileInfo(html);
            //判断文件是否已经存在,如果存在就删除! 
            if (fi.Exists)
            {
                fi.Delete();
            }

            object format = MSWord.WdSaveFormat.wdFormatDocument;
            //将wordDoc文档对象的内容保存为DOCX文档      
            wordDoc.SaveAs(html);
            //关闭wordDoc文档对象       
            wordDoc.Close(ref Nothing, ref Nothing, ref Nothing);
            //关闭wordApp组件对象       
            wordApp.Quit(ref Nothing, ref Nothing, ref Nothing);
        }

        public bool ConvertHtmlUrlToMht(string htmlUrl, string filePath)
        {
            bool isConvertHtmlBytesToMht = false;
            CDO.Message message = new CDO.Message();
            ADODB.Stream stream = null;
            message.MimeFormatted = true;
            message.CreateMHTMLBody(htmlUrl, CDO.CdoMHTMLFlags.cdoSuppressNone, "", "");
            stream = message.GetStream();
            stream.SaveToFile(filePath, ADODB.SaveOptionsEnum.adSaveCreateOverWrite);
            message = null;
            stream.Close();
            isConvertHtmlBytesToMht = true;
            return isConvertHtmlBytesToMht;
        }
        private void ToImage(string base64, string filePath, int toWidth, int toHeight)
        {
            MemoryStream stream = new MemoryStream(Convert.FromBase64String(base64));

            Bitmap img = new Bitmap(stream);
            Image toImg = ScaleImage(img, toWidth, toHeight);
            toImg.Save(filePath, ImageFormat.Png);
        }
        public Image ScaleImage(Image originalImage, int toWidth, int toHeight)
        {
            if (toWidth <= 0 || toHeight <= 0)
            {
                return originalImage;
            }

            Image toBitmap = new Bitmap(toWidth, toHeight);
            using (Graphics g = Graphics.FromImage(toBitmap))
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.Clear(Color.Transparent);
                g.DrawImage(originalImage,
                            new System.Drawing.Rectangle(0, 0, toWidth, toHeight),
                            new System.Drawing.Rectangle(0, 0, originalImage.Width, originalImage.Height),
                            GraphicsUnit.Pixel);
                originalImage.Dispose();
                return toBitmap;
            }
        }
        public Document SaveAsWord(string fileName)//使用原生方法将mht转换为word文档，不是那种直接修改后缀名的方式
        {
            object missing = System.Reflection.Missing.Value;
            object readOnly = false;
            object isVisible = true;
            object file1 = fileName;
            //object html1 = pFileName;
            object format = WdSaveFormat.wdFormatDocument;
            wordApp = new MSWord.Application();
            wordApp.Visible = false;
            Document oWordDoc = wordApp.Documents.Open(ref   file1, ref   format, ref   readOnly, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref missing);
            wordApp.ActiveWindow.View.Type = Microsoft.Office.Interop.Word.WdViewType.wdPrintView;//将web视图修改为默认视图，不然打开word的时候会以web视图去展示，而不是默认视图。（唯独这句代码是自己加的 = =|||）

            oWordDoc.Save();
            return oWordDoc;
            //oWordDoc.SaveAs(ref   html1, ref   format, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing, ref   missing,ref   missing, ref   missing, ref   missing, ref   missing, ref   missing);
            //oWordDoc.Close(ref     missing, ref     missing, ref     missing);
            //oWordDoc = null;
            //wordApp.Application.Quit(ref   missing, ref   missing, ref   missing);
            //wordApp = null;

        }

        /// <summary>
        /// 把流转文件           
        /// </summary>
        /// <param name="stream">数据流</param>
        /// <param name="fileName">文件保存物理路径</param>
        public void StreamToFile(Stream stream, string fileName)
        {
            try
            {
                // 把 Stream 转换成 byte[] 
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);
                // 设置当前流的位置为流的开始 
                stream.Seek(0, SeekOrigin.Begin);
                // 把 byte[] 写入文件 
                FileStream fs = new FileStream(fileName, FileMode.Create);
                BinaryWriter bw = new BinaryWriter(fs, Encoding.UTF8);
                bw.Write(bytes);
                bw.Close();
                fs.Close();
            }
            catch (exception)
            {
                throw new ArgumentException("流转文件过程出错");
            }
        }

        /// <summary>
        /// 数据转换为内存流
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public Stream GetStream(string str)
        {
            if (!string.IsNullOrEmpty(str))
            {
                MemoryStream ms = new MemoryStream();
                //using (StreamWriter sw = new StreamWriter(ms))
                //{
                StreamWriter sw = new StreamWriter(ms);
                sw.Write(str);
                sw.Flush();
                ms.Position = 0;
                //}
                return ms;
            }
            return null;
        }

        public string decodeHtml(string html)
        {
            if (!string.IsNullOrEmpty(html))
            {
                return html.Replace("&lt", "<").Replace("&gt", ">");
            }
            else
                return "";
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

    }

    public class imageModel
    {
        public string name { get; set; }
        public string base64 { get; set; }
        public Int16 width { get; set; }
        public Int16 height { get; set; }
    }

    public class ResultModel
    {
        public ResultModel()
        {

        }
        public ResultModel(string message, string fileURL, string filePath)
        {
            this.message = message;
            this.fileURL = fileURL;
            this.filePath = filePath;
        }
        public string message;
        public string fileURL;
        public string filePath;
    }

}